home *** CD-ROM | disk | FTP | other *** search
/ Gekikoh Dennoh Club 5 / Gekikoh Dennoh Club Vol. 5 (Japan).7z / Gekikoh Dennoh Club Vol. 5 (Japan) (Track 01).bin / internet / xip / iijppp.lzh / src / fsm.c < prev    next >
C/C++ Source or Header  |  1994-10-11  |  16KB  |  801 lines

  1. /*
  2.  *        PPP Finite State Machine for LCP/IPCP
  3.  *
  4.  *        Written by Toshiharu OHNO (tony-o@iij.ad.jp)
  5.  *
  6.  *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
  7.  *
  8.  * Redistribution and use in source and binary forms are permitted
  9.  * provided that the above copyright notice and this paragraph are
  10.  * duplicated in all such forms and that any documentation,
  11.  * advertising materials, and other materials related to such
  12.  * distribution and use acknowledge that the software was developed
  13.  * by the Internet Initiative Japan, Inc.  The name of the
  14.  * IIJ may not be used to endorse or promote products derived
  15.  * from this software without specific prior written permission.
  16.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  17.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  18.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  19.  *
  20.  *  TODO:
  21.  *        o Refer loglevel for log output
  22.  *        o Better option log display
  23.  */
  24. #include "fsm.h"
  25. #include "hdlc.h"
  26. #include "lqr.h"
  27. #include "lcpproto.h"
  28. #include "lcp.h"
  29.  
  30. void FsmSendConfigReq(struct fsm *fp);
  31. void FsmSendTerminateReq(struct fsm *fp);
  32. void FsmInitRestartCounter(struct fsm *fp);
  33. void FsmTimeout(struct fsm *fp);
  34.  
  35. char *StateNames[] = {
  36.   "Initial", "Starting", "Closed", "Stopped", "Closing", "Stopping",
  37.   "Req-Sent", "Ack-Rcvd", "Ack-Sent", "Opend",
  38. };
  39.  
  40. void
  41. FsmInit(fp)
  42. struct fsm *fp;
  43. {
  44. #ifdef DEBUG
  45.   logprintf("FsmInit\n");
  46. #endif
  47.   fp->state = ST_INITIAL;
  48.   fp->reqid = 1;
  49.   fp->restart = 1;
  50.   fp->maxconfig = 3;
  51. }
  52.  
  53. void
  54. NewState(fp, new)
  55. struct fsm *fp;
  56. int new;
  57. {
  58.   LogPrintf(LOG_LCP, "%s: state change %s --> %s\n",
  59.       fp->name, StateNames[fp->state], StateNames[new]);
  60.   fp->state = new;
  61.   if ((new >= ST_INITIAL && new <= ST_STOPPED) || (new == ST_OPENED))
  62.     StopTimer(&fp->FsmTimer);
  63. }
  64.  
  65. void
  66. FsmOutput(fp, code, id, ptr, count)
  67. struct fsm *fp;
  68. u_int code, id;
  69. u_char *ptr;
  70. int count;
  71. {
  72.   int plen;
  73.   struct fsmheader lh;
  74.   struct mbuf *bp;
  75.  
  76.   plen =  sizeof(struct fsmheader) + count;
  77.   lh.code = code;
  78.   lh.id = id;
  79.   lh.length = htons(plen);
  80.   bp = mballoc(plen, MB_FSM);
  81.   bcopy(&lh, MBUF_CTOP(bp), sizeof(struct fsmheader));
  82.   if (count)
  83.     bcopy(ptr, MBUF_CTOP(bp) + sizeof(struct fsmheader), count);
  84. #ifdef DEBUG
  85.   DumpBp(bp);
  86. #endif
  87.   HdlcOutput(PRI_NORMAL, fp->proto, bp);
  88. }
  89.  
  90. void
  91. FsmOpen(fp)
  92. struct fsm *fp;
  93. {
  94.   switch (fp->state) {
  95.   case ST_INITIAL:
  96.     (fp->LayerStart)(fp);
  97.     NewState(fp, ST_STARTING);
  98.     break;
  99.   case ST_STARTING:
  100.     break;
  101.   case ST_CLOSED:
  102.     if (fp->open_mode == OPEN_PASSIVE) {
  103.       NewState(fp, ST_STOPPED);
  104.     } else {
  105.       FsmInitRestartCounter(fp);
  106.       FsmSendConfigReq(fp);
  107.       NewState(fp, ST_REQSENT);
  108.     }
  109.     break;
  110.   case ST_STOPPED:    /* XXX: restart option */
  111.   case ST_REQSENT:
  112.   case ST_ACKRCVD:
  113.   case ST_ACKSENT:
  114.   case ST_OPENED:    /* XXX: restart option */
  115.     break;
  116.   case ST_CLOSING:    /* XXX: restart option */
  117.   case ST_STOPPING:    /* XXX: restart option */
  118.     NewState(fp, ST_STOPPING);
  119.     break;
  120.   }
  121. }
  122.  
  123. void
  124. FsmUp(fp)
  125. struct fsm *fp;
  126. {
  127.   switch (fp->state) {
  128.   case ST_INITIAL:
  129.     NewState(fp, ST_CLOSED);
  130.     break;
  131.   case ST_STARTING:
  132.     FsmInitRestartCounter(fp);
  133.     FsmSendConfigReq(fp);
  134.     NewState(fp, ST_REQSENT);
  135.     break;
  136.   default:
  137.     LogPrintf(LOG_LCP, "%s: Oops, Up at %s\n",
  138.         fp->name, StateNames[fp->state]);
  139.     break;
  140.   }
  141. }
  142.  
  143. void
  144. FsmDown(fp)
  145. struct fsm *fp;
  146. {
  147.   switch (fp->state) {
  148.   case ST_CLOSED:
  149.   case ST_CLOSING:
  150.     NewState(fp, ST_INITIAL);
  151.     break;
  152.   case ST_STOPPED:
  153.     (fp->LayerStart)(fp);
  154.     /* Fall into.. */
  155.   case ST_STOPPING:
  156.   case ST_REQSENT:
  157.   case ST_ACKRCVD:
  158.   case ST_ACKSENT:
  159.     NewState(fp, ST_STARTING);
  160.     break;
  161.   case ST_OPENED:
  162.     (fp->LayerDown)(fp);
  163.     NewState(fp, ST_STARTING);
  164.     break;
  165.   }
  166. }
  167.  
  168. void
  169. FsmClose(fp)
  170. struct fsm *fp;
  171. {
  172.   switch (fp->state) {
  173.   case ST_STARTING:
  174.     NewState(fp, ST_INITIAL);
  175.     break;
  176.   case ST_STOPPED:
  177.     NewState(fp, ST_CLOSED);
  178.     break;
  179.   case ST_STOPPING:
  180.     NewState(fp, ST_CLOSING);
  181.     break;
  182.   case ST_OPENED:
  183.     (fp->LayerDown)(fp);
  184.     /* Fall down */
  185.   case ST_REQSENT:
  186.   case ST_ACKRCVD:
  187.   case ST_ACKSENT:
  188.     FsmInitRestartCounter(fp);
  189.     FsmSendTerminateReq(fp);
  190.     NewState(fp, ST_CLOSING);
  191.     break;
  192.   }
  193. }
  194.  
  195. /*
  196.  *    Send functions
  197.  */
  198. void
  199. FsmSendConfigReq(fp)
  200. struct fsm *fp;
  201. {
  202.   if (--fp->maxconfig > 0) {
  203.     (fp->SendConfigReq)(fp);
  204.     StartTimer(&fp->FsmTimer);    /* Start restart timer */
  205.     fp->restart--;        /* Decrement restart counter */
  206.   } else {
  207.     FsmClose(fp);
  208.   }
  209. }
  210.  
  211. void
  212. FsmSendTerminateReq(fp)
  213. struct fsm *fp;
  214. {
  215.   LogPrintf(LOG_LCP, "%s: SendTerminateReq.\n", fp->name);
  216.   FsmOutput(fp, CODE_TERMREQ, fp->reqid++, NULL, 0);
  217.   (fp->SendTerminateReq)(fp);
  218.   StartTimer(&fp->FsmTimer);    /* Start restart timer */
  219.   fp->restart--;        /* Decrement restart counter */
  220. }
  221.  
  222. static void
  223. FsmSendConfigAck(fp, lhp, option, count)
  224. struct fsm *fp;
  225. struct fsmheader *lhp;
  226. u_char *option;
  227. int count;
  228. {
  229.   LogPrintf(LOG_LCP, "%s:  SendConfigAck(%s)\n", fp->name, StateNames[fp->state]);
  230.   FsmOutput(fp, CODE_CONFIGACK, lhp->id, option, count);
  231. }
  232.  
  233. static void
  234. FsmSendConfigRej(fp, lhp, option, count)
  235. struct fsm *fp;
  236. struct fsmheader *lhp;
  237. u_char *option;
  238. int count;
  239. {
  240.   LogPrintf(LOG_LCP, "%s:  SendConfigRej(%s)\n", fp->name, StateNames[fp->state]);
  241.   FsmOutput(fp, CODE_CONFIGREJ, lhp->id, option, count);
  242. }
  243.  
  244. static void
  245. FsmSendConfigNak(fp, lhp, option, count)
  246. struct fsm *fp;
  247. struct fsmheader *lhp;
  248. u_char *option;
  249. int count;
  250. {
  251.   LogPrintf(LOG_LCP, "%s:  SendConfigNak(%s)\n",
  252.         fp->name, StateNames[fp->state]);
  253.   FsmOutput(fp, CODE_CONFIGNAK, lhp->id, option, count);
  254. }
  255.  
  256. /*
  257.  *    Timeout actions
  258.  */
  259. void
  260. FsmTimeout(fp)
  261. struct fsm *fp;
  262. {
  263.   if (fp->restart) {
  264.     switch (fp->state) {
  265.     case ST_CLOSING:
  266.     case ST_STOPPING:
  267.       FsmSendTerminateReq(fp);
  268.       break;
  269.     case ST_REQSENT:
  270.     case ST_ACKSENT:
  271.       FsmSendConfigReq(fp);
  272.       break;
  273.     case ST_ACKRCVD:
  274.       FsmSendConfigReq(fp);
  275.       NewState(fp, ST_REQSENT);
  276.       break;
  277.     }
  278.     StartTimer(&fp->FsmTimer);
  279.   } else {
  280.     switch (fp->state) {
  281.     case ST_CLOSING:
  282.       NewState(fp, ST_CLOSED);
  283.       (fp->LayerFinish)(fp);
  284.       break;
  285.     case ST_STOPPING:
  286.       NewState(fp, ST_STOPPED);
  287.       (fp->LayerFinish)(fp);
  288.       break;
  289.     case ST_REQSENT:        /* XXX: 3p */
  290.     case ST_ACKSENT:
  291.     case ST_ACKRCVD:
  292.       NewState(fp, ST_STOPPED);
  293.       (fp->LayerFinish)(fp);
  294.       break;
  295.     }
  296.   }
  297. }
  298.  
  299. void
  300. FsmInitRestartCounter(fp)
  301. struct fsm *fp;
  302. {
  303.   StopTimer(&fp->FsmTimer);
  304.   fp->FsmTimer.state = TIMER_STOPPED;
  305.   fp->FsmTimer.func = FsmTimeout;
  306.   fp->FsmTimer.arg = (void *)fp;
  307.   (fp->InitRestartCounter)(fp);
  308. }
  309.  
  310. /*
  311.  *   Actions when receive packets
  312.  */
  313. void
  314. FsmRecvConfigReq(fp, lhp, bp)            /* RCR */
  315. struct fsm *fp;
  316. struct fsmheader *lhp;
  317. struct mbuf *bp;
  318. {
  319.   int plen;
  320.   int ackaction = 0;
  321.  
  322.   plen = plength(bp);
  323.   if (plen < sizeof(struct fsmconfig)) {
  324. logprintf("** plen = %d\n", plen);
  325.     pfree(bp);
  326.     return;
  327.   }
  328.  
  329.   /*
  330.    *  Check and process easy case
  331.    */
  332.   switch (fp->state) {
  333.   case ST_INITIAL:
  334.   case ST_STARTING:
  335.     LogPrintf(LOG_LCP, "%s: Oops, RCR in %s.\n",
  336.         fp->name, StateNames[fp->state]);
  337.     pfree(bp);
  338.     return;
  339.   case ST_CLOSED:
  340.     (fp->SendTerminateAck)(fp);
  341.     pfree(bp);
  342.     return;
  343.   case ST_CLOSING:
  344.   case ST_STOPPING:
  345. logprintf("## state = %d\n", fp->state);
  346.     pfree(bp);
  347.     return;
  348.   }
  349.  
  350.   (fp->DecodeConfig)(bp, MODE_REQ);
  351.  
  352.   if (nakp == NakBuff && rejp == RejBuff)
  353.     ackaction = 1;
  354.  
  355.   switch (fp->state) {
  356.   case ST_OPENED:
  357.     (fp->LayerDown)(fp);
  358.     FsmSendConfigReq(fp);
  359.     break;
  360.   case ST_STOPPED:
  361.     FsmInitRestartCounter(fp);
  362.     FsmSendConfigReq(fp);
  363.     break;
  364.   }
  365.  
  366.   if (rejp != RejBuff)
  367.     FsmSendConfigRej(fp, lhp, RejBuff, rejp - RejBuff);
  368.   if (nakp != NakBuff)
  369.     FsmSendConfigNak(fp, lhp, NakBuff, nakp - NakBuff);
  370.   if (ackaction)
  371.     FsmSendConfigAck(fp, lhp, AckBuff, ackp - AckBuff);
  372.  
  373.   switch (fp->state) {
  374.   case ST_STOPPED:
  375.   case ST_OPENED:
  376.     if (ackaction)
  377.       NewState(fp, ST_ACKSENT);
  378.     else
  379.       NewState(fp, ST_REQSENT);
  380.     break;
  381.   case ST_REQSENT:
  382.     if (ackaction)
  383.       NewState(fp, ST_ACKSENT);
  384.     break;
  385.   case ST_ACKRCVD:
  386.     if (ackaction) {
  387.       NewState(fp, ST_OPENED);
  388.       (fp->LayerUp)(fp);
  389.     }
  390.     break;
  391.   case ST_ACKSENT:
  392.     if (!ackaction)
  393.       NewState(fp, ST_REQSENT);
  394.     break;
  395.   }
  396.   pfree(bp);
  397. }
  398.  
  399. void
  400. FsmRecvConfigAck(fp, lhp, bp)            /* RCA */
  401. struct fsm *fp;
  402. struct fsmheader *lhp;
  403. struct mbuf *bp;
  404. {
  405.   switch (fp->state) {
  406.   case ST_CLOSED:
  407.   case ST_STOPPED:
  408.     (fp->SendTerminateAck)(fp);
  409.     break;
  410.   case ST_CLOSING:
  411.   case ST_STOPPING:
  412.     break;
  413.   case ST_REQSENT:
  414.     FsmInitRestartCounter(fp);
  415.     NewState(fp, ST_ACKRCVD);
  416.     break;
  417.   case ST_ACKRCVD:
  418.     FsmSendConfigReq(fp);
  419.     NewState(fp, ST_REQSENT);
  420.     break;
  421.   case ST_ACKSENT:
  422.     FsmInitRestartCounter(fp);
  423.     NewState(fp, ST_OPENED);
  424.     (fp->LayerUp)(fp);
  425.     break;
  426.   case ST_OPENED:
  427.     (fp->LayerDown)(fp);
  428.     FsmSendConfigReq(fp);
  429.     NewState(fp, ST_REQSENT);
  430.     break;
  431.   }
  432.   pfree(bp);
  433. }
  434.  
  435. void
  436. FsmRecvConfigNak(fp, lhp, bp)            /* RCN */
  437. struct fsm *fp;
  438. struct fsmheader *lhp;
  439. struct mbuf *bp;
  440. {
  441.   int plen;
  442.  
  443.   plen = plength(bp);
  444.   if (plen < sizeof(struct fsmconfig)) {
  445.     pfree(bp);
  446.     return;
  447.   }
  448.  
  449.   /*
  450.    *  Check and process easy case
  451.    */
  452.   switch (fp->state) {
  453.   case ST_INITIAL:
  454.   case ST_STARTING:
  455.     LogPrintf(LOG_LCP, "%s: Oops, RCN in %s.\n",
  456.         fp->name, StateNames[fp->state]);
  457.     pfree(bp);
  458.     return;
  459.   case ST_CLOSED:
  460.   case ST_STOPPED:
  461.     (fp->SendTerminateAck)(fp);
  462.     pfree(bp);
  463.     return;
  464.   case ST_CLOSING:
  465.   case ST_STOPPING:
  466.     pfree(bp);
  467.     return;
  468.   }
  469.  
  470.   (fp->DecodeConfig)(bp, MODE_NAK);
  471.  
  472.   switch (fp->state) {
  473.   case ST_REQSENT:
  474.   case ST_ACKSENT:
  475.     FsmInitRestartCounter(fp);
  476.     FsmSendConfigReq(fp);
  477.     break;
  478.   case ST_OPENED:
  479.     (fp->LayerDown)(fp);
  480.     /* Fall down */
  481.   case ST_ACKRCVD:
  482.     FsmSendConfigReq(fp);
  483.     NewState(fp, ST_REQSENT);
  484.     break;
  485.   }
  486.  
  487.   pfree(bp);
  488. }
  489.  
  490. void
  491. FsmRecvTermReq(fp, lhp, bp)                /* RTR */
  492. struct fsm *fp;
  493. struct fsmheader *lhp;
  494. struct mbuf *bp;
  495. {
  496.   switch (fp->state) {
  497.   case ST_INITIAL:
  498.   case ST_STARTING:
  499.     LogPrintf(LOG_LCP, "%s: Oops, RTR in %s\n", fp->name,
  500.         StateNames[fp->state]);
  501.     break;
  502.   case ST_CLOSED:
  503.   case ST_STOPPED:
  504.   case ST_CLOSING:
  505.   case ST_STOPPING:
  506.   case ST_REQSENT:
  507.     (fp->SendTerminateAck)(fp);
  508.     break;
  509.   case ST_ACKRCVD:
  510.   case ST_ACKSENT:
  511.     (fp->SendTerminateAck)(fp);
  512.     NewState(fp, ST_REQSENT);
  513.     break;
  514.   case ST_OPENED:
  515.     (fp->LayerDown)(fp);
  516.     /* Zero Restart counter */
  517.     (fp->SendTerminateAck)(fp);
  518.     NewState(fp, ST_STOPPING);
  519.     break;
  520.   }
  521.   pfree(bp);
  522. }
  523.  
  524. void
  525. FsmRecvTermAck(fp, lhp, bp)            /* RTA */
  526. struct fsm *fp;
  527. struct fsmheader *lhp;
  528. struct mbuf *bp;
  529. {
  530.   switch (fp->state) {
  531.   case ST_CLOSING:
  532.     NewState(fp, ST_CLOSED);
  533.     (fp->LayerFinish)(fp);
  534.     break;
  535.   case ST_STOPPING:
  536.     NewState(fp, ST_STOPPED);
  537.     (fp->LayerFinish)(fp);
  538.     break;
  539.   case ST_ACKRCVD:
  540.     NewState(fp, ST_REQSENT);
  541.     break;
  542.   case ST_OPENED:
  543.     (fp->LayerDown)(fp);
  544.     FsmSendConfigReq(fp);
  545.     NewState(fp, ST_REQSENT);
  546.     break;
  547.   }
  548.   pfree(bp);
  549. }
  550.  
  551. void
  552. FsmRecvConfigRej(fp, lhp, bp)            /* RCJ */
  553. struct fsm *fp;
  554. struct fsmheader *lhp;
  555. struct mbuf *bp;
  556. {
  557.   int plen;
  558.  
  559.   plen = plength(bp);
  560.   if (plen < sizeof(struct fsmconfig)) {
  561.     pfree(bp);
  562.     return;
  563.   }
  564.   LogPrintf(LOG_LCP, "%s: RecvConfigRej.\n", fp->name);
  565.  
  566.   /*
  567.    *  Check and process easy case
  568.    */
  569.   switch (fp->state) {
  570.   case ST_INITIAL:
  571.   case ST_STARTING:
  572.     LogPrintf(LOG_LCP, "%s: Oops, RCJ in %s.\n",
  573.         fp->name, StateNames[fp->state]);
  574.     pfree(bp);
  575.     return;
  576.   case ST_CLOSED:
  577.   case ST_STOPPED:
  578.     (fp->SendTerminateAck)(fp);
  579.     pfree(bp);
  580.     return;
  581.   case ST_CLOSING:
  582.   case ST_STOPPING:
  583.     pfree(bp);
  584.     return;
  585.   }
  586.  
  587.   (fp->DecodeConfig)(bp, MODE_REJ);
  588.  
  589.   switch (fp->state) {
  590.   case ST_REQSENT:
  591.   case ST_ACKSENT:
  592.     FsmInitRestartCounter(fp);
  593.     FsmSendConfigReq(fp);
  594.     break;
  595.   case ST_OPENED:
  596.     (fp->LayerDown)(fp);
  597.     /* Fall down */
  598.   case ST_ACKRCVD:
  599.     FsmSendConfigReq(fp);
  600.     NewState(fp, ST_REQSENT);
  601.     break;
  602.   }
  603.   pfree(bp);
  604. }
  605.  
  606. void
  607. FsmRecvCodeRej(fp, lhp, bp)
  608. struct fsm *fp;
  609. struct fsmheader *lhp;
  610. struct mbuf *bp;
  611. {
  612.   LogPrintf(LOG_LCP, "%s: RecvCodeRej\n", fp->name);
  613.   pfree(bp);
  614. }
  615.  
  616. void
  617. FsmRecvProtoRej(fp, lhp, bp)
  618. struct fsm *fp;
  619. struct fsmheader *lhp;
  620. struct mbuf *bp;
  621. {
  622.   u_short *sp, proto;
  623.  
  624.   sp = (u_short *)MBUF_CTOP(bp);
  625.   proto = ntohs(*sp);
  626.   LogPrintf(LOG_LCP, "-- Protocol (%04x) was rejected.\n", proto);
  627.  
  628.   switch (proto) {
  629.   case PROTO_LQR:
  630.     StopLqr(LQM_LQR);
  631.     break;
  632.   case PROTO_CCP:
  633.     fp = &CcpFsm;
  634.     (fp->LayerFinish)(fp);
  635.     switch (fp->state) {
  636.     case ST_CLOSED:
  637.     case ST_CLOSING:
  638.       NewState(fp, ST_CLOSED);
  639.     default:
  640.       NewState(fp, ST_STOPPED);
  641.       break;
  642.     }
  643.     break;
  644.   }
  645.   pfree(bp);
  646. }
  647.  
  648. void
  649. FsmRecvEchoReq(fp, lhp, bp)
  650. struct fsm *fp;
  651. struct fsmheader *lhp;
  652. struct mbuf *bp;
  653. {
  654.   u_char *cp;
  655.   u_long *lp, magic;
  656.  
  657.   cp = MBUF_CTOP(bp);
  658.   lp = (u_long *)cp;
  659.   magic = ntohl(*lp);
  660.   if (magic != LcpInfo.his_magic) {
  661.     logprintf("RecvEchoReq: his magic is bad!!\n");
  662.     /* XXX: We should send terminate request */
  663.   }
  664.  
  665.   if (fp->state == ST_OPENED) {
  666.     *lp = htonl(LcpInfo.want_magic);    /* Insert local magic number */
  667.     LogPrintf(LOG_LCP, "%s:  SendEchoRep(%s)\n", fp->name, StateNames[fp->state]);
  668.     FsmOutput(fp, CODE_ECHOREP, lhp->id, cp, plength(bp));
  669.   }
  670.   pfree(bp);
  671. }
  672.  
  673. void
  674. FsmRecvEchoRep(fp, lhp, bp)
  675. struct fsm *fp;
  676. struct fsmheader *lhp;
  677. struct mbuf *bp;
  678. {
  679.   u_long *lp, magic;
  680.  
  681.   lp = (u_long *)MBUF_CTOP(bp);
  682.   magic = ntohl(*lp);
  683.   if (magic != 0 && magic != LcpInfo.his_magic) {
  684.     logprintf("RecvEchoRep: his magic is wrong! expect: %x got: %x\n",
  685.     LcpInfo.his_magic, magic);
  686.     /*
  687.      *  XXX: We should send terminate request. But poor implementation
  688.      *       may die as a result.
  689.      */
  690.   }
  691.   RecvEchoLqr(bp);
  692.   pfree(bp);
  693. }
  694.  
  695. void
  696. FsmRecvDiscReq(fp, lhp, bp)
  697. struct fsm *fp;
  698. struct fsmheader *lhp;
  699. struct mbuf *bp;
  700. {
  701.   LogPrintf(LOG_LCP, "%s: RecvDiscReq\n", fp->name);
  702.   pfree(bp);
  703. }
  704.  
  705. void
  706. FsmRecvIdent(fp, lhp, bp)
  707. struct fsm *fp;
  708. struct fsmheader *lhp;
  709. struct mbuf *bp;
  710. {
  711.   LogPrintf(LOG_LCP, "%s: RecvIdent\n", fp->name);
  712.   pfree(bp);
  713. }
  714.  
  715. void
  716. FsmRecvTimeRemain(fp, lhp, bp)
  717. struct fsm *fp;
  718. struct fsmheader *lhp;
  719. struct mbuf *bp;
  720. {
  721.   LogPrintf(LOG_LCP, "%s: RecvTimeRemain\n", fp->name);
  722.   pfree(bp);
  723. }
  724.  
  725. void
  726. FsmRecvResetReq(fp, lhp, bp)
  727. struct fsm *fp;
  728. struct fsmheader *lhp;
  729. struct mbuf *bp;
  730. {
  731.   LogPrintf(LOG_LCP, "%s: RecvResetReq\n", fp->name);
  732.   CcpRecvResetReq(fp);
  733.   LogPrintf(LOG_LCP, "%s: SendResetAck\n", fp->name);
  734.   FsmOutput(fp, CODE_RESETACK, fp->reqid, NULL, 0);
  735.   pfree(bp);
  736. }
  737.  
  738. void
  739. FsmRecvResetAck(fp, lhp, bp)
  740. struct fsm *fp;
  741. struct fsmheader *lhp;
  742. struct mbuf *bp;
  743. {
  744.   LogPrintf(LOG_LCP, "%s: RecvResetAck\n", fp->name);
  745.   fp->reqid++;
  746.   pfree(bp);
  747. }
  748.  
  749. struct fsmcodedesc FsmCodes[] = {
  750.  { FsmRecvConfigReq,  "Configure Request", },
  751.  { FsmRecvConfigAck,  "Configure Ack", },
  752.  { FsmRecvConfigNak,  "Configure Nak", },
  753.  { FsmRecvConfigRej,  "Configure Reject", },
  754.  { FsmRecvTermReq,    "Terminate Request", },
  755.  { FsmRecvTermAck,    "Terminate Ack", },
  756.  { FsmRecvCodeRej,    "Code Reject", },
  757.  { FsmRecvProtoRej,   "Protocol Reject", },
  758.  { FsmRecvEchoReq,    "Echo Request", },
  759.  { FsmRecvEchoRep,    "Echo Reply", },
  760.  { FsmRecvDiscReq,    "Discard Request", },
  761.  { FsmRecvIdent,      "Ident", },
  762.  { FsmRecvTimeRemain, "Time Remain", },
  763.  { FsmRecvResetReq,   "Reset Request", },
  764.  { FsmRecvResetAck,   "Reset Ack", },
  765. };
  766.  
  767. void
  768. FsmInput(fp, bp)
  769. struct fsm *fp;
  770. struct mbuf *bp;
  771. {
  772.   int len;
  773.   struct fsmheader *lhp;
  774.   struct fsmcodedesc *codep;
  775.  
  776.   len = plength(bp);
  777.   if (len < sizeof(struct fsmheader)) {
  778.     pfree(bp);
  779.     return;
  780.   }
  781.   lhp = (struct fsmheader *)MBUF_CTOP(bp);
  782.   if (lhp->code == 0 || lhp->code > fp->max_code) {
  783.     pfree(bp);        /* XXX: Should send code reject */
  784.     return;
  785.   }
  786.  
  787.   bp->offset += sizeof(struct fsmheader);
  788.   bp->cnt -= sizeof(struct fsmheader);
  789.  
  790.   codep = FsmCodes + lhp->code - 1;
  791.   LogPrintf(LOG_LCP, "%s: Received %s (%d) state = %s (%d)\n",
  792.     fp->name, codep->name, lhp->code, StateNames[fp->state], fp->state);
  793. #ifdef DEBUG
  794.   LogMemory();
  795. #endif
  796.   (codep->action)(fp, lhp, bp);
  797. #ifdef DEBUG
  798.   LogMemory();
  799. #endif
  800. }
  801.